﻿
using Sustainalytics.Auth.Common;
using Sustainalytics.Entities;
using System;
using System.Collections.Generic;
using FakeItEasy;
using Sustainalytics.DataLayer;
using Xunit;

namespace Sustainalytics.AuthOperations.Tests
{
    [Trait("Category", "Unit")]

    public class AuthOperationsTests
    {
        private readonly Dictionary<string, string> serviceBusParams = new Dictionary<string, string>
        {
            { "ConnectionString", "Endpoint=sb://sust-test-ns.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Dh/4Cq0qrOC7xOJFUYHLGJvQ6pqj4BuwjTS4HUjL6uQ=" },
            { "RegionEndpoint", "TT" },
            { "SessionId", "Auth" },
            { "TopicPath", "test-topic" },
        };

        [Fact]
        public void ResetPasswordByUserIds()
        {
            Guid _userid = Guid.Parse("4349590a-c370-4d40-bb0f-2865fadd0d55");
            var _expirationDate = DateTime.UtcNow.AddDays(7);

            var _savedTempKey = Guid.Empty.ToString();
            var _savedExpirationDate = DateTime.MinValue;

            var _username = "mihai.stanescu@sustainalytics.com";

            var accountsRepository = A.Fake<IAccountsRepository>();
            A.CallTo(() => accountsRepository.SavePasswordByUserId(_userid, A<string>._, A<DateTime>._)).Invokes((call) => { _savedTempKey = call.GetArgument<string>(1); _savedExpirationDate = call.GetArgument<DateTime>(2); });

            A.CallTo(() => accountsRepository.GetUserByUserId(_userid)).Returns(new User() { Id = _userid, Email = _username, FirstName = "Mihai", LastName = "Stanescu" });

            var authOperations = new AuthOperations(accountsRepository, "http://localhost:10280", serviceBusParams);
            authOperations.ResetPasswordByUserIds(new List<Guid>());

            authOperations.ResetPasswordByUserIds(new List<Guid>() { _userid });
            Assert.Equal(_expirationDate.Date, _savedExpirationDate.Date);
        }

        [Fact]
        public void ResetPasswordByUsername()
        {
            var _username = "mihai.stanescu@sustainalytics.com";
            var _expirationDate = DateTime.UtcNow.AddDays(7);

            var _savedTempKey = Guid.Empty.ToString();
            var _savedExpirationDate = DateTime.MinValue;

            var accountsRepository = A.Fake<IAccountsRepository>();

            A.CallTo(() => accountsRepository.SavePasswordByUsername(A<string>._, A<string>._, A<DateTime>._)).Invokes((call) => { _savedTempKey = call.GetArgument<string>(1); _savedExpirationDate = call.GetArgument<DateTime>(2); });
            A.CallTo(() => accountsRepository.GetUserByUsername(A<string>._)).Returns(new User() { Id = Guid.NewGuid(), Email = _username, FirstName = "Mihai", LastName = "Stanescu" });


            var authOperations = new AuthOperations(accountsRepository, "http://localhost:10280", serviceBusParams);

            authOperations.ResetPasswordByUsername(_username, PasswordEmailMessageBody.PasswordReset);

            Assert.Equal(_expirationDate.Date, _savedExpirationDate.Date);
        }

        [Fact]
        public void ChangePassword()
        {
            var _username = "mihai.stanescu@sustainalytics.com";
            var _password = "Password99#";
            var _expirationDate = DateTime.UtcNow.AddMonths(6);

            var _savedPassword = "";
            var _savedExpirationDate = DateTime.MinValue;

            var accountsRepository = A.Fake<IAccountsRepository>();

            A.CallTo(() => accountsRepository.SavePasswordByUsername(A<string>._, A<string>._, A<DateTime>._)).Invokes((call) => { _savedPassword = call.GetArgument<string>(1); _savedExpirationDate = call.GetArgument<DateTime>(2); });
            A.CallTo(() => accountsRepository.GetUserByUsername(A<string>._)).Returns(new User() { Id = Guid.NewGuid(), Email = _username, FirstName = "Mihai", LastName = "Stanescu" });

            var authOperations = new AuthOperations (accountsRepository, "http://localhost:10280", serviceBusParams);

            authOperations.SetPassword(_username, _password);

            Assert.True(PasswordManager.VerifyHashedPassword(_savedPassword, _password), "The saved password is different from the expected one.");
            Assert.Equal(_expirationDate.Date, _savedExpirationDate.Date);
        }

        [Fact]
        public void ValidateAccountStatus()
        {
            var _username = "mihai.stanescu@sustainalytics.com";

            var accountsRepository = A.Fake<IAccountsRepository>();
            A.CallTo(() => accountsRepository.GetUserByUsername(A<string>._)).Returns(new User() { Id = Guid.NewGuid(), Status = Status.Active });


            var authOperations = new AuthOperations(accountsRepository, "http://localhost:10280", serviceBusParams);

            bool _accountIsActive = authOperations.ValidateAccountStatus(_username);

            Assert.True(_accountIsActive, "The account status validation is invalid.");
        }

        [Fact]
        public void ValidatePasswordStatus()
        {
            var _username = "mihai.stanescu@sustainalytics.com";

            var accountsRepository = A.Fake<IAccountsRepository>();
            A.CallTo(() => accountsRepository.GetClientUserByUsername(A<string>._)).Returns(new ClientUser() { Id = Guid.NewGuid(), Password = "Password99#", PasswordExpirationDate = DateTime.UtcNow.AddDays(1) });


            var authOperations = new AuthOperations(accountsRepository, "http://localhost:10280", serviceBusParams);

            bool _passwordIsActive = authOperations.ValidatePasswordStatus(_username);

            Assert.True(_passwordIsActive, "The password status validation is invalid.");
        }
    }
}
